﻿#region  
//=====================================================
// 文件名: AssetBundleLoadReource                
// 创建者: #AuthorName#                
// 创建时间: #CreateTime#              	
// Email: #AuthorEmail#               
// 描述: 当前脚本的功能              
// 修改者列表: 修改者名字以及修改功能      
// 版权所有: #Copyright#                 
//======================================================
#endregion 



using FrameWork.AB;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace FrameWork.Reource
{

    public class AssetBundleLoadReource : IResourceLoad
    {
        public override T LoadResource<T>(string path)
        {
            if (string.IsNullOrEmpty(path))
                return null;

            uint crc = CRC32.GetCRC32(path);

            ResourceItem item = GetCacheResourceItem(crc, 1);

            if (item != null)
                return item.m_obj as T;

            T obj = null;
            item = AssetBundleManager.Instance.LoadResoureceAssetBundle(crc);

            if (item != null && item.LoadCompletedAssetBundle != null)
            {
                if (item.m_obj != null)
                    obj = (T)item.m_obj;
                else
                    obj = item.LoadCompletedAssetBundle.LoadAsset<T>(item.AssetName);
            }

            if (obj == null)
                Debug.LogError("There is no object to load :" + path);


            CacheResource(path, ref item, crc, obj);

            return obj;
        }

        public override void Init(MonoBehaviour mono)
        {
            base.Init(mono);
            mMono.StartCoroutine(SyncLoad());
        }

        IEnumerator SyncLoad()
        {
            long lastYiedTime = System.DateTime.Now.Ticks;
            while (true)
            {
                bool haveYield = false;
                for (int i = 0; i < (int)LoadResPriority.RES_NUM; i++)
                {
                    List<AsyncLoadResParm> loadingList = mLoadingAssetList[i];
                    if (loadingList.Count <= 0)
                    {
                        continue;
                    }

                    AsyncLoadResParm loadingItem = loadingList[0];
                    loadingList.RemoveAt(0);
                    List<AsyncCallBack> callBackList = loadingItem.mCallBackList;

                    Object obj = null;
                    ResourceItem item = AssetBundleManager.Instance.LoadResoureceAssetBundle(loadingItem.mCrc);

                    if (item != null && item.LoadCompletedAssetBundle != null)
                    {
                        AssetBundleRequest abRequest = JudgeLoadType(loadingItem, item);

                        yield return abRequest;
                        if (abRequest.isDone)
                        {
                            obj = abRequest.asset;
                        }
                        lastYiedTime = System.DateTime.Now.Ticks;
                    }
                    else
                    {
                        Debug.LogError("Resource or assetbundle is empty.");
                    }

                    //Debug.LogErrorFormat("Load is :{0},A type of：{1}", obj, obj.GetType());

                    CacheResource(loadingItem.mPath, ref item, loadingItem.mCrc, obj, callBackList.Count);

                    for (int j = 0; j < callBackList.Count; j++)
                    {
                        AsyncCallBack callBack = callBackList[j];
                        if (callBack != null && callBack.mDealFinish != null)
                        {
                            callBack.mDealFinish(loadingItem.mPath, obj, callBack.mParme);
                            callBack.mDealFinish = null;
                        }
                        callBack.Reset();
                        mAsyncCallBackPool.Recycle(callBack);
                    }

                    callBackList.Clear();
                    mLoadingAssetDic.Remove(loadingItem.mCrc);

                    loadingItem.Reset();
                    mAsyncLoadResParamPool.Recycle(loadingItem);

                    if (System.DateTime.Now.Ticks - lastYiedTime > MAXLOADRESTIME)
                    {
                        yield return null;
                        lastYiedTime = System.DateTime.Now.Ticks;
                        haveYield = true;
                    }
                }
                if (!haveYield || System.DateTime.Now.Ticks - lastYiedTime > MAXLOADRESTIME)
                {
                    yield return null;
                    lastYiedTime = System.DateTime.Now.Ticks;
                }
                yield return null;
            } 
        }

        private AssetBundleRequest JudgeLoadType(AsyncLoadResParm loadingItem, ResourceItem item)
        {
            if (loadingItem.mType == typeof(Sprite))
            {
                return item.LoadCompletedAssetBundle.LoadAssetAsync<Sprite>(item.AssetName);
            }
            else
            {
                return item.LoadCompletedAssetBundle.LoadAssetAsync<Object>(item.AssetName);
            }
        }

        /// 回收资源（删除资源）
        public override void DestoryResourceItem(ResourceItem item, bool destoryCache = false)
        {

            if (!CanDestoryResourceItem(item,destoryCache))
            {
                return;
            }

            AssetBundleManager.Instance.ReleaseAsset(item);

            if (item.m_obj != null)
            {
                item.m_obj = null;
            }
        }


        //资源预加载
        public override void PreloadRes(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return;
            }

            uint crc = CRC32.GetCRC32(path);

            ResourceItem item = GetCacheResourceItem(crc, 0);

            if (item != null)
                return;

            Object obj = null;
            item = AssetBundleManager.Instance.LoadResoureceAssetBundle(crc);

            if (item != null && item.LoadCompletedAssetBundle != null)
            {
                if (item.m_obj != null)
                    obj = item.m_obj;
                else
                    obj = item.LoadCompletedAssetBundle.LoadAsset<Object>(item.AssetName);
            }

            if (obj == null)
                Debug.LogError("There is no object to load :" + path);


            CacheResource(path, ref item, crc, obj);

            item.m_Clear = false;//跳场景不清空这个资源

            ReleaseResource(obj, false);
        }
    }
}